/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package session.stateless.MRP.SaleForecast;

import entity.Product;
import entity.MRP.SaleForecast.AnnualSaleForecast;
import entity.MRP.SaleForecast.MonthlySaleFigure;
import entity.MRP.SaleForecast.MonthlySaleForecast;
import entity.MRP.SaleForecast.SaleFigureLineItem;
import entity.MRP.SaleForecast.SaleForecastLineItem;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javaclass.ProductType;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.Query;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import session.stateless.ProductBeanLocal;

/**
 *
 * @author Vincent
 */
@Stateless
public class SaleForecastBean implements SaleForecastBeanLocal {
    
    @PersistenceContext (unitName = "M10-IS3102-ejbPU")
    private EntityManager entityManager; 
    @EJB
    SaleFigureBeanLocal saleFigureBeanLocal;
    @EJB
    ProductBeanLocal productBeanLocal;

    @Override
    public List<MonthlySaleForecast> getMonthlySaleForecasts(int year, int startPeriod, int endPeriod){
        System.out.println(year + " " + startPeriod + " " + endPeriod);
        Query query = entityManager.createQuery("SELECT a FROM AnnualSaleForecast a WHERE a.saleForecastYear = :inSaleForecastYear");
        query.setParameter("inSaleForecastYear", year);
        AnnualSaleForecast annualSaleForecast = null;
        try 
        { 
            annualSaleForecast = (AnnualSaleForecast) query.getSingleResult();
        } 
        catch(NoResultException ex) 
        { 
            //ex.printStackTrace(); 
        } 
        if (annualSaleForecast == null){
             this.generateAnnualSaleForecastsBase(year);
             return null;
        }
        List<MonthlySaleForecast> monthlySaleForecasts = new ArrayList<MonthlySaleForecast>();
        for (int i = startPeriod; i <= endPeriod; i++){
            MonthlySaleForecast saleForecast = annualSaleForecast.getMonthlySaleForecasts().get(i);
                monthlySaleForecasts.add(saleForecast);
        }
        return monthlySaleForecasts;
        
    }
    
    @Override
    public List<Integer> getSaleForecastMonths(){
        Calendar currentDate = Calendar.getInstance();
        int currentMonth = currentDate.get(Calendar.MONTH);
        int i = 0;
        int month = currentMonth;
        List<Integer> months = new ArrayList<Integer>();
        while (i <= 11){
            i++;
            months.add(month);
            month++;
            if (month > 11){
                month = 0;
            }
        }
        return months;
    }
    
    @Override
    public boolean generateSaleForecasts(int startMonth, int startYear, int endMonth, int endYear){
        List<MonthlySaleFigure> monthlySaleFigures = new ArrayList<MonthlySaleFigure>();
        List<MonthlySaleForecast> monthlySaleForecasts = new ArrayList<MonthlySaleForecast>();
        if (startYear == endYear){
            int i = startMonth;
            while (i <= endMonth){
                MonthlySaleFigure m = saleFigureBeanLocal.getMonthlySaleFigure(startYear - 1, i);
                if (m.getTotalProductCaseQuantityWithoutPromotion() == 0){
                    return false;
                }
                monthlySaleFigures.add(m);
                i++;
            }
            monthlySaleForecasts = this.getMonthlySaleForecasts(startYear, startMonth, endMonth);
            if (monthlySaleForecasts == null){
                System.out.println("True");
                monthlySaleForecasts = this.getMonthlySaleForecasts(startYear, startMonth, endMonth);
            }
            if (monthlySaleForecasts == null){
                System.out.println("True");
                monthlySaleForecasts = this.getMonthlySaleForecasts(startYear, startMonth, endMonth);
            }
            AnnualSaleForecast annualSaleForecast = this.getAnnualSaleForecast(startYear);
            double yearOverYearGrowth = annualSaleForecast.getYearOverYearGrowth();
            for (int index = 0; index < monthlySaleFigures.size(); index++){
                for(SaleFigureLineItem s:monthlySaleFigures.get(index).getSaleFigureLineItems()){
                    if (monthlySaleForecasts.get(index).getTotalProductCaseQuantityWithoutPromotion() == 0){
                        this.updateSaleForecast(startYear, monthlySaleForecasts.get(index).getSaleForecastMonth(), s.getProduct(), (long)(s.getQuantityInCases() * (100 + yearOverYearGrowth) / 100), 0);
                    }
                }
                
            }
        }
        else{
            int i = startMonth;
            while (i <= 11){
                MonthlySaleFigure m = saleFigureBeanLocal.getMonthlySaleFigure(startYear - 1, i);
                if (m.getTotalProductCaseQuantityWithoutPromotion() == 0){
                    return false;
                }
                monthlySaleFigures.add(m);
                i++;
            }
            monthlySaleForecasts = this.getMonthlySaleForecasts(startYear, startMonth, 11);
            if (monthlySaleForecasts == null){
                System.out.println("True 1");
                monthlySaleForecasts = this.getMonthlySaleForecasts(startYear, startMonth, 11);
            }
            if (monthlySaleForecasts == null){
                System.out.println("True 2");
                monthlySaleForecasts = this.getMonthlySaleForecasts(startYear, startMonth, 11);
            }            
            AnnualSaleForecast annualSaleForecast = this.getAnnualSaleForecast(startYear);
            double yearOverYearGrowth = annualSaleForecast.getYearOverYearGrowth();
            for (int index = 0; index < monthlySaleFigures.size(); index++){
                for(SaleFigureLineItem s:monthlySaleFigures.get(index).getSaleFigureLineItems()){
                    if (monthlySaleForecasts.get(index).getTotalProductCaseQuantityWithoutPromotion() == 0){
                        this.updateSaleForecast(startYear, monthlySaleForecasts.get(index).getSaleForecastMonth(), s.getProduct(), (long)(s.getQuantityInCases() * (100 + yearOverYearGrowth) / 100), 0);
                    }
                }
                
            }
            
            i = 0;
            monthlySaleFigures = new ArrayList<MonthlySaleFigure>();
            while (i <= endMonth){
                MonthlySaleFigure m = saleFigureBeanLocal.getMonthlySaleFigure(startYear, i);
                if (m.getTotalProductCaseQuantityWithoutPromotion() == 0){
                    return false;
                }
                monthlySaleFigures.add(m);
                i++;
            }
            monthlySaleForecasts = this.getMonthlySaleForecasts(endYear, 0, endMonth);
            if (monthlySaleForecasts == null){
                System.out.println("True 3");
                monthlySaleForecasts = this.getMonthlySaleForecasts(endYear, 0, endMonth);
            }
            if (monthlySaleForecasts == null){
                System.out.println("True 4");
                monthlySaleForecasts = this.getMonthlySaleForecasts(endYear, 0, endMonth);
            }
            annualSaleForecast = this.getAnnualSaleForecast(endYear);
            yearOverYearGrowth = annualSaleForecast.getYearOverYearGrowth();
            for (int index = 0; index < monthlySaleFigures.size(); index++){
                for(SaleFigureLineItem s:monthlySaleFigures.get(index).getSaleFigureLineItems()){
                    if (monthlySaleForecasts.get(index).getTotalProductCaseQuantityWithoutPromotion() == 0){
                        this.updateSaleForecast(endYear, monthlySaleForecasts.get(index).getSaleForecastMonth(), s.getProduct(), (long)(s.getQuantityInCases() * (100 + yearOverYearGrowth) / 100), 0);
                    }
                }
            }
        }

        return true;
    }
    
    public void generateAnnualSaleForecastsBase(int year){
        AnnualSaleForecast annualSaleForecast = new AnnualSaleForecast();
        annualSaleForecast.setSaleForecastYear(year);
        List<MonthlySaleForecast> monthlySaleForecasts = new ArrayList<MonthlySaleForecast>();
        for (int i = 0; i <= 11; i++){
            MonthlySaleForecast monthlySaleForecast = new MonthlySaleForecast();
            monthlySaleForecast.setSaleForecastMonth(i);
            List<SaleForecastLineItem> saleForecastLineItems = new ArrayList<SaleForecastLineItem>();
            List<Product> productList = productBeanLocal.getProductList();
            for (Product p:productList){
                SaleForecastLineItem saleForecastLineItem = new SaleForecastLineItem();
                saleForecastLineItem.setProduct(p);
                saleForecastLineItem.setQuantityInCases((long)0);
                saleForecastLineItem.setPromotionQuantityInCases((long)0);
                saleForecastLineItems.add(saleForecastLineItem);
                entityManager.persist(saleForecastLineItem);
            }
            monthlySaleForecast.setSaleForecastLineItems(saleForecastLineItems);
            entityManager.persist(monthlySaleForecast);
            monthlySaleForecasts.add(i, monthlySaleForecast);
        }
        annualSaleForecast.setMonthlySaleForecasts(monthlySaleForecasts);
        annualSaleForecast.setYearOverYearGrowth(3);
        entityManager.persist(annualSaleForecast);
    }
    
    @Override
    public AnnualSaleForecast getAnnualSaleForecast(int year){
        Query query = entityManager.createQuery("SELECT a FROM AnnualSaleForecast a WHERE a.saleForecastYear = :inSaleForecastYear");
        query.setParameter("inSaleForecastYear", year);
        AnnualSaleForecast annualSaleForecast = null;
        try 
        { 
            annualSaleForecast = (AnnualSaleForecast) query.getSingleResult();
        } 
        catch(NoResultException ex) 
        { 
            //ex.printStackTrace(); 
        } 
        if (annualSaleForecast == null){
            this.generateAnnualSaleForecastsBase(year);
        }
        return annualSaleForecast;
    }
    
    @Override
    public void updateSaleForecast(int year, int month, Product product, long quantityInCases, long promotionQuantityInCases){
        Query query = entityManager.createQuery("SELECT a FROM AnnualSaleForecast a WHERE a.saleForecastYear = :inSaleFigureYear");
        query.setParameter("inSaleFigureYear", year);
        AnnualSaleForecast annualSaleForecast = null;
        try 
        { 
            annualSaleForecast = (AnnualSaleForecast) query.getSingleResult();
        } 
        catch(NoResultException ex) 
        { 
            //ex.printStackTrace(); 
        } 
        if (annualSaleForecast == null){
            this.generateAnnualSaleForecastsBase(year);
        }
        List<SaleForecastLineItem> saleForecastLineItems = annualSaleForecast.getMonthlySaleForecasts().get(month).getSaleForecastLineItems();
        for(SaleForecastLineItem s:saleForecastLineItems){
            if (s.getProduct().equals(product)){
                SaleForecastLineItem saleForecastLineItem = entityManager.find(SaleForecastLineItem.class, s.getId());
                saleForecastLineItem.setQuantityInCases(quantityInCases);
                saleForecastLineItem.setPromotionQuantityInCases(promotionQuantityInCases);
                entityManager.flush();
            }
        }
        
    }

    @Override
    public void editSaleForecast(long monthId, List<SaleForecastLineItem> saleForecastLineItems){
        MonthlySaleForecast monthlySaleForecast = entityManager.find(MonthlySaleForecast.class, monthId);
        for(SaleForecastLineItem s:monthlySaleForecast.getSaleForecastLineItems()){
            this.updateSaleForecastLineItem(s.getId(), findInListSaleFigure(s.getProduct().getProductType(), saleForecastLineItems));
        }
    }  
    
    public void updateSaleForecastLineItem(long saleForecastLineItemId, SaleForecastLineItem saleForecastLineItem){
        SaleForecastLineItem s = entityManager.find(SaleForecastLineItem.class, saleForecastLineItemId);
        s.setQuantityInCases(saleForecastLineItem.getQuantityInCases());
        s.setPromotionQuantityInCases(saleForecastLineItem.getPromotionQuantityInCases());
        entityManager.flush();
    }
    
    public SaleForecastLineItem findInListSaleFigure(ProductType productType, List<SaleForecastLineItem> saleForecastLineItems){
        boolean check = false;
        for(SaleForecastLineItem s:saleForecastLineItems){
            if (s.getProduct().getProductType() == productType){
                return s;
            }
        }
        return null;
    }    
}
